package com.aidex.biz.utils;


import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * AES加密器
 * <p>
 * 默认128位加密
 */
@Slf4j
public class RongXiangKeAESUtil {

    private RongXiangKeAESUtil() {
    }

    private static final String AES_ALGORITHM = "AES";
    public static final String HOST = "https://gw.rongxk.cn";
    public static final String VOUCHER_CODE = "130416622490290585644fd3a3755e3451eaff4880bfae1b49d";
    public static final String KEY = "2dcf49bb06f67b04";

    /**
     * 加密
     *
     * @param data 待加密内容
     * @param key  加密秘钥
     * @return 十六进制字符串
     */
    public static String encrypt(String data, String key) {
        if (key.length() < 16) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        } else if (key.length() > 16) {
            key = key.substring(0, 16);
        }
        try {
            // 创建密码器
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
            byte[] byteContent = data.getBytes(StandardCharsets.UTF_8);
            // 初始化
            cipher.init(Cipher.ENCRYPT_MODE, genKey(key));
            byte[] result = cipher.doFinal(byteContent);
            // 加密
            return parseByte2HexStr(result);
        } catch (Exception e) {
            log.error("数据加密失败", e);
            throw new RuntimeException("数据加密失败");
        }
    }

    /**
     * 解密
     *
     * @param data 待解密内容(十六进制字符串)
     * @param key  加密秘钥
     */
    public static String decrypt(String data, String key) {
        if (key.length() < 16) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        } else if (key.length() > 16) {
            key = key.substring(0, 16);
        }
        try {
            byte[] decryptFrom = parseHexStr2Byte(data);
            // 创建密码器
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, genKey(key));
            byte[] result = cipher.doFinal(decryptFrom);
            // 加密
            return new String(result, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("数据解密失败", e);
            throw new RuntimeException("数据解密失败");
        }
    }

    /**
     * 创建加密解密密钥
     *
     * @param key 加密解密密钥
     */
    private static SecretKeySpec genKey(String key) {
        SecretKeySpec secretKey;
        try {
            secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
            byte[] enCodeFormat = secretKey.getEncoded();
            return new SecretKeySpec(enCodeFormat, AES_ALGORITHM);
        } catch (Exception e) {
            log.error("生成密钥失败", e);
            throw new RuntimeException("genKey fail!");
        }
    }

    /**
     * 将二进制转换成16进制
     */
    private static String parseByte2HexStr(byte[] buf) {
        StringBuilder sb = new StringBuilder();
        for (byte b : buf) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     */
    private static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.isEmpty()) {
            return new byte[0];
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {
        //aesKey为双方约定的密钥
        String aesKey = "1234567890123456";
        String data = "18811111***";
        String encryptData = RongXiangKeAESUtil.encrypt(data, aesKey);
        log.info("加密后数据：{}", encryptData);
        String decryptData = RongXiangKeAESUtil.decrypt(encryptData, aesKey);
        log.info("解密后数据：{}", decryptData);
    }
}
